﻿
package extremefx.unitTest {
	import flash.utils.Dictionary;
	import flash.utils.describeType;
	import flash.utils.getQualifiedClassName;		

	/**
	 * @author Marcelo Volmaro
	 */
	public final class Trace {
		private static var _knownObjs:Dictionary;
		
		public static function obj(pObj:*):String {
			_knownObjs = new Dictionary(true);
			var txt:String = _analyzeObj(pObj, 1);
			_knownObjs = null;
			return txt;
		}
		
		private static function _analyzeObj(pObj:*, pLevel:uint):String {
			var txt:String = "";
			var name:String = getQualifiedClassName(pObj);
			var analize:Boolean = false;
			
			switch (name){
				case "String":
					txt += "\""+pObj+"\"";
					break;
				
				case "Boolean":
				case "Number":
				case "int":
				case "uint":
					txt += pObj;
					break;
					
				case "undefined":
				case "null":
					txt += "("+name+")";
					break;
					
				case "Date":
					txt += (pObj as Date).toLocaleString();
					break;
				
				default:
					analize = _knownObjs[pObj] == null;
					var dt:XML = _knownObjs[pObj] = describeType(pObj);
					txt += "("+dt.@name+")";
					
					if (analize){
						var txtProps1:String = "";
						
						for (var prop:String in pObj){
							if (pObj[prop] === pObj) continue;
							txtProps1 += "\n" + multiply( "\t", (pLevel+1) ) + prop + ":" + _analyzeObj(pObj[prop], (pLevel+1));
						}
					
						var txtProps2:String  = "";
						for each(var xml:XML in dt..accessor) {
							prop = xml.@name;
							if (pObj[prop] === pObj) continue;
							txtProps2 += "\n" + multiply( "\t", (pLevel+1) ) + prop + ":" + _analyzeObj(pObj[prop], (pLevel+1));
						}
						
						var txtProps3:String  = "";
						for each(var xml2:XML in dt..variable) {
							prop = xml2.@name;
							if (pObj[prop] === pObj) continue;
							txtProps3 += "\n" + multiply( "\t", (pLevel+1) ) + prop + ":" + _analyzeObj(pObj[prop], (pLevel+1));
						}
						
						if (txtProps1.length || txtProps2.length || txtProps3.length){
							txt += "{";
							if (txtProps1.length) txt += "\n"+multiply( "\t", pLevel)+"[Properties]" + txtProps1 + "\n" + multiply("\t", pLevel);	
							if (txtProps2.length) txt += "\n"+multiply( "\t", pLevel)+"[Accessors]" + txtProps2 + "\n" + multiply("\t", pLevel);	
							if (txtProps3.length) txt += "\n"+multiply( "\t", pLevel)+"[Variables]" + txtProps3 + "\n" + multiply("\t", pLevel);
							txt += "}";	
						}
						
//						if(txtProps.length > 0) txt += "{" + txtProps + "\n" + multiply( "\t", pLevel ) + "}";
						
					}
			}
			
			return txt;
		}
		
		private static function multiply(str:String, n:Number):String {
			var ret:String = "";
			do {
				ret += str;
			} while (--n);
			return ret;
		}
	}
}
